package game.jabberclient;


import game.MainGame.WorldMemoryGame;
import game.gui.buttons.FirstLbl;

import java.net.*;
import java.io.*;

/**
 * Game client. Communicates through GUI with server. Listens for incoming
 * messages.
 * 
 */
public class Client {

	private Socket socket;
	private WorldMemoryGame gui;
	private String server;
	private final String username;
	private int port;
	private ObjectInputStream netIn; // to read from the socket
	private ObjectOutputStream netOut; // to write on the socket
	private int clientId = 0;
	private FirstLbl button;
	private boolean firstMove = true;
	private boolean history = false;
	private boolean art = false;
	private boolean geography = false;
	private boolean science = false;
	private boolean sport = false;
	private boolean varia = false;

	public boolean isHistory() {
		return history;
	}

	public void setHistory(boolean history) {
		this.history = history;
	}

	public boolean isArt() {
		return art;
	}

	public void setArt(boolean art) {
		this.art = art;
	}

	public boolean isGeography() {
		return geography;
	}

	public void setGeography(boolean geography) {
		this.geography = geography;
	}

	public boolean isScience() {
		return science;
	}

	public void setScience(boolean science) {
		this.science = science;
	}

	public boolean isSport() {
		return sport;
	}

	public void setSport(boolean sport) {
		this.sport = sport;
	}

	public boolean isVaria() {
		return varia;
	}

	public void setVaria(boolean varia) {
		this.varia = varia;
	}

	public ObjectOutputStream getNetOut() {
		return netOut;
	}

	private Message message;

	public Client(String server, int port, String username,
			WorldMemoryGame gui, FirstLbl button) {
		this.server = server;
		this.port = port;
		this.username = username;
		this.gui = gui;
		this.button = button;
	}

	public FirstLbl getClientButton() {
		return button;
	}

	public void setClientButton(FirstLbl button) {
		this.button = button;
	}

	public String getName() {
		return this.username;
	}

	public int getClientId() {
		return clientId;
	}

	private void setClientId(String msg) {
		if (getClientId() == 0) {
			String[] s = msg.split(" ", 2);
			clientId = Integer.parseInt(s[0]);
		}
	}

	public boolean start() {
		try {
			socket = new Socket(server, port);
		} catch (IOException e) {
			display("Error connectiong to server:" + e);
			return false;
		}
		String msg = "Connection accepted " + socket.getInetAddress() + ":"
				+ socket.getPort();
		display(msg);
		try {
			netIn = new ObjectInputStream(socket.getInputStream());
			netOut = new ObjectOutputStream(socket.getOutputStream());
		} catch (IOException e) {
			display("Exception creating new Input/output Streams: " + e);
			return false;
		}
		// creates the Thread to listen from the server
		new ListenFromServer().start();
		// sends client username for the server.
		try {
			netOut.writeObject(username);
			display("Welcome " + username);
		} catch (IOException e) {
			display("Exception during login : " + e);
			disconnect();
			return false;
		}
		return true;
	}

	/**
	 * Displays message on the GUI's JTextArea
	 * 
	 * @param msg
	 *            message
	 */
	private void display(String msg) {
		gui.append(msg + "\n");
	}

	/**
	 * Send message to the server.
	 * 
	 * @param msg
	 *            Message.
	 */
	public void sendMessage(Message msg) {
		try {
			netOut.writeObject(msg);
		} catch (IOException e) {
			display("Exception writing to server: " + e);
		}
	}

	// Try to close all the connections when exiting.
	public void disconnect() {
		try {
			if (netIn != null)
				netIn.close();
		} catch (Exception e) {
		}
		try {
			if (netOut != null)
				netOut.close();
		} catch (Exception e) {
		}
		try {
			if (socket != null)
				socket.close();
		} catch (Exception e) {
		}
		if (gui != null)
			gui.connectionFailed();
	}

	/**
	 * Listens Messages from Server.
	 * 
	 * @author Mina
	 * 
	 */
	class ListenFromServer extends Thread {
		public void run() {
			while (true) {
				try {
					message = (Message) netIn.readObject();
				} catch (IOException e) {
					display(" Connection lost with server... ");
					break;
				} catch (ClassNotFoundException e) {
					break;
				}
				// if console mode print the message and add back the prompt
				String msg = message.getMessage();
				switch (message.getType()) {
				case Message.VICTORY:
					String[] num1 = msg.split(" ");
					System.out.println("sain katte " + num1[3]);
					if (num1[3].equals("victorious")) {
						display("Player " + num1[1] + " has won the game!");
					} else {
						display("Player " + num1[1] + " has finished game.");
					}
					for (FirstLbl f : gui.getHistory1().getButtons()) {
						if (f.getIndex() == Integer.parseInt(num1[2])) {
							f.removePlayer(Integer.parseInt(num1[0]));
						}
					}
					break;
				case Message.TURN:
					display("Your turn to roll!");
					gui.getBtnDie().setEnabled(true);
					break;
				case Message.MESSAGE:
					display(msg);
					break;
				case Message.START:
					if(gui.getStart().isEnabled()){
						gui.getStart().setEnabled(false);
					}
					break;
				
				case Message.LOGOUT:
					String[] num = msg.split(" ");
					for (FirstLbl f : gui.getHistory1().getButtons()) {
						if (f.getIndex() == Integer.parseInt(num[1])) {
							f.removePlayer(Integer.parseInt(num[0]));
						}
					}
					display("Player " + num[3] + " has left the game.");
					gui.removePlayerName(num[2] + " " + num[3]);
					break;
				case Message.NEWPL:
					setClientId(msg);
					gui.appendPlayer(msg + "\n");
					break;
				case Message.DICE:
					display(msg);
					break;
				case Message.MOVE:
					if (firstMove) {
						firstMove = false;
						try {
							netOut
									.writeObject(new Message(Message.IN,
											"false"));
						} catch (IOException e) {}
					}
					movePlayer(msg);
					break;
				default:
					display("Nothing");
				}
			}
		}

		/**
		 * Moves client's id around.
		 * 
		 * @param s
		 *            Message string.
		 */
		private void movePlayer(String s) {
			String[] num = s.split(" ");
			for (FirstLbl f : gui.getHistory1().getButtons()) {
				f.removePlayer(Integer.parseInt(num[0]));
				if (f.getIndex() == Integer.parseInt(num[1])) {
					f.addPlayer(Integer.parseInt(num[0]));
				}
			}
		}

	}
}
